package x.ovo.wechat.bot.impl.event;

import lombok.NonNull;
import org.dromara.hutool.core.text.StrUtil;
import x.ovo.wechat.bot.core.event.Event;
import x.ovo.wechat.bot.core.event.EventListener;
import x.ovo.wechat.bot.core.event.EventManager;
import x.ovo.wechat.bot.core.event.MessageEvent;
import x.ovo.wechat.bot.core.plugin.Plugin;
import x.ovo.wechat.bot.impl.plugin.DefaultPluginManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public enum DefaultEventManager implements EventManager {
    INSTANCE;

    private final List<Plugin> plugins = new ArrayList<>();

    @Override
    public void register(@NonNull Plugin plugin) {

        // 根据插件优先级进行二分查找，排序插入
        int i = Collections.binarySearch(plugins, plugin, Comparator.comparingInt(Plugin::getPriority));
        if (i < 0) i = -(i + 1);
        plugins.add(i, plugin);

        log.debug("[{}] 事件监听器注册成功", plugin.getPluginDesc().getName());
    }

    @Override
    public void unregister(@NonNull Plugin plugin) {
        plugins.removeIf(plugin::equals);
        log.debug("[{}] 事件监听器注销成功", plugin.getPluginDesc().getName());
    }

    @Override
    @SuppressWarnings({"rawtypes", "unchecked"})
    public void fireEvent(@NonNull Event<?> event) {
        log.debug("[{}] 事件触发: {}", StrUtil.defaultIfBlank(event.getClass().getSimpleName(), "未知事件"), event.getSource());
        // 遍历所有插件，以寻找与当前事件匹配并应被触发的插件
        for (Plugin plugin : this.plugins) {
            // 如果是群消息事件，检查插件是否在限制名单中
            if (event instanceof MessageEvent<?> messageEvent && messageEvent.getSource().isGroup()) {
                String pluginName = plugin.getPluginDesc().getName();
                String nickName = messageEvent.getSource().getFrom().getNickName();
                if (DefaultPluginManager.INSTANCE.isLimit(pluginName, nickName)) {
                    log.debug("[{}] 事件触发被限制，{} 不可触发该监听器", pluginName, nickName);
                    continue;
                }
            }
            // 如果插件未启用，则跳过该插件的处理
            if (!plugin.isEnabled()) continue;

            // 尝试从映射中获取与当前插件对应的事件监听器
            EventListener listener = plugin.getEventListener();
            // 如果监听器不存在，则跳过当前插件
            if (listener == null) continue;
            // 检查事件类型是否匹配监听器期望的事件类型
            if (!listener.getEventClass().isAssignableFrom(event.getClass())) continue;
            // 检查事件源类型是否匹配监听器期望的事件源类型
            if (!listener.getSourceClass().isAssignableFrom(event.getSource().getClass())) continue;


            // 根据监听器的判断条件，确认是否支持处理当前事件和事件来源
            if (!listener.support(event, event.getSource())) continue;

            // 触发事件处理方法
            boolean executeResult = listener.onEvent(event, event.getSource());
            log.debug("[{}] 监听到事件，是否执行: {}", plugin.getPluginDesc().getName(), executeResult);

            // 检查是否应继续处理下一个监听器
            if (executeResult && !listener.executeNext()) {
                log.debug("[{}] 事件监听处理成功，且不执行后续监听器", plugin.getPluginDesc().getName());
                break;
            }
        }

    }
}
